﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.IO;
using AutoLoL.Entities;

namespace AutoLoL.Logic.Parsers
{
    public class InibinParser
    {
        public static Dictionary<uint, InibinEntry> ParseFile(string path)
        {
            return ParseBytes(File.ReadAllBytes(path));
        }

        public static Dictionary<uint, InibinEntry> ParseBytes(byte[] buffer)
        {
            Dictionary<uint, InibinEntry> result = new Dictionary<uint, InibinEntry>();

            int bufferStart = 0;
            int bufferLength = buffer.Length;

            byte version = buffer[bufferStart];
            ushort dataLength = BitConverter.ToUInt16(buffer, bufferStart + 1);
            ushort segments = BitConverter.ToUInt16(buffer, bufferStart + 3);
            int startIndex = bufferStart + 5;

            for (int i = 0; segments != 0; i++)
            {
                if ((segments & 1) != 0)
                {
                    int segmentItemCount = BitConverter.ToUInt16(buffer, startIndex);
                    int segmentItemSize = InibinEntry.SegmentSizes[i];
                    int keyArraySize = segmentItemCount * sizeof(UInt32);
                    int valueArraySize = (segmentItemSize == -1) ? ((segmentItemCount + 7) / 8) : (segmentItemCount * segmentItemSize);

                    for (int j = 0; j < segmentItemCount; j++)
                    {
                        // TODO - Added try catch to quick-fix Talon patch
                        try
                        {
                            int keyOffset = (startIndex + sizeof(UInt16)) + (j * sizeof(UInt32));
                            uint key = BitConverter.ToUInt32(buffer, keyOffset);
                            int valueOffset = ((startIndex + sizeof(UInt16)) + keyArraySize) + ((segmentItemSize == -1) ? (j / 8) : (j * segmentItemSize));
                            int dataOffset = -1;
                            int bitNumber = -1;

                            switch (i)
                            {
                                case 5:
                                    {
                                        bitNumber = j % 8;
                                        break;
                                    }
                                case 12:
                                    {
                                        ushort value = BitConverter.ToUInt16(buffer, valueOffset);
                                        dataOffset = ((bufferStart + bufferLength) - dataLength) + value;
                                        break;
                                    }
                            }

                            result.Add(key, new InibinEntry(key, buffer, i, valueOffset, dataOffset, bitNumber));
                        }
                        catch { if (Debugger.IsAttached) throw; }
                    }

                    startIndex += (sizeof(UInt16) + keyArraySize) + valueArraySize;
                }

                segments = (ushort)(segments >> 1);
            }

            return result;
        }
    }
}
